package com.csun.cmny.provider.controller;

import com.csun.cmny.base.dto.LoginAuthDto;
import com.csun.cmny.core.annotation.ValidateAnnotation;
import com.csun.cmny.core.support.BaseController;
import com.csun.cmny.provider.config.RedisInitRunner;
import com.csun.cmny.provider.dto.BedDto;
import com.csun.cmny.provider.model.domain.OmcLevelCare;
import com.csun.cmny.provider.model.dto.BedInfoQueryDto;
import com.csun.cmny.provider.model.dto.BedOldmanQueryDto;
import com.csun.cmny.provider.model.vo.*;
import com.csun.cmny.provider.pojo.Bed;
import com.csun.cmny.provider.pojo.Building;
import com.csun.cmny.provider.pojo.Room;
import com.csun.cmny.provider.resolver.CmnyMessageSource;
import com.csun.cmny.provider.service.*;
import com.csun.cmny.provider.vo.BedVo;
import com.csun.cmny.util.PublicUtil;
import com.csun.cmny.util.RedisKeyUtil;
import com.csun.cmny.util.wrapper.WrapMapper;
import com.csun.cmny.util.wrapper.Wrapper;
import com.google.common.base.Preconditions;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/*
 * 床位管理
 * */
@RestController
@RequestMapping("/Bed")
public class BedController extends BaseController {

    @Resource
    private RedisInitRunner redisInitRunner;

    @Autowired
    private BedService bedService;

    @Autowired
    private RoomService roomService;

    @Resource
    private DmcRpcService dmcRpcService;

    @Resource
    private CmnyMessageSource cmnyMessageSource;

    @Resource
    private BuildingService buildingService;

    @Resource
    private RedisTemplate<String,Object>redisTemplate;

    @Resource
    private OmcLevelCareService levelCareService;
    /*
     * 这里的认证和当前登录的用户注解先预留，等完善了再进行修改
     * 1.判断该用户是否属于该机构人员
     * */
    //添加床位
    @RequestMapping(value = "/addBed", method = RequestMethod.POST)
    public Wrapper addBed(Bed bed) {
        //校验
        if (StringUtils.isEmpty(bed.getBedNo())) {
//            return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, "床位编号不能为空", null);
            return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, cmnyMessageSource.getMessage("Bed.number.null", null), null);
        }
        if (bed.getBedDirection() == null) {
//            return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, "床位朝向不能为空", null);
            return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, cmnyMessageSource.getMessage("bed.direction.null", null), null);
        }
        if (bed.getRoomId() == null) {
//            return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, "房间id不能为空", null);
            return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, cmnyMessageSource.getMessage("room.id.null", null), null);
        }
        //获取机构id
        LoginAuthDto loginAuthDto = getLoginAuthDto();
        Integer homeId = loginAuthDto.getGroupId().intValue();
        //Integer homeId = 1001;
        //查询该楼栋的床位编号方式(1 按房间计数 2 按楼层计数)及房间信息
        Map<String, Object> buildingAndRoom = roomService.selectBuildingAndRoom(bed.getRoomId());
        //获取编号方式
        Integer bedNoType = (Integer) buildingAndRoom.get("bedNoType");
        Bed bed1 = new Bed();
        bed1.setBedNo(bed.getBedNo());
        bed1.setRoomId(bed.getRoomId());
        //按照房间计数
        if (bedNoType != null && bedNoType == 1) {
            //根据房间id和房间编号查询床位编号在该房间中是否重复
            Bed bedCheck = new Bed();
            bedCheck.setBedNo(bed.getBedNo());
            bedCheck.setRoomId(bed.getRoomId());
            bedCheck = bedService.selectByBed(bedCheck);
            if (bedCheck != null) {
//                return WrapMapper.wrap(Wrapper.ERROR_CODE, "该床位已经在房间中存在", null);
                return WrapMapper.wrap(Wrapper.ERROR_CODE, cmnyMessageSource.getMessage("Bed.have.repeat.num", null), null);
            }
        }
        //按照楼层计数
        if (bedNoType != null && bedNoType == 2) {
            //根据房间id和房间编号查询床位编号在楼层中是否重复
            Bed bed3 = bedService.selectByRidAndBedNo(bed1);
            if (bed3 != null) {
//                return WrapMapper.wrap(Wrapper.ERROR_CODE, "该床位已经在楼层中存在", null);
                return WrapMapper.wrap(Wrapper.ERROR_CODE, cmnyMessageSource.getMessage("Bed.floor.repeat.num", null), null);
            }
        }
        //修改房间表中床位数量的值
        Integer bedNum = (Integer) buildingAndRoom.get("bedNum");
        if (bedNum == null) {
            bedNum = 1;
        } else {
            bedNum += 1;
        }
        Room room = new Room();
        room.setRoomId(bed.getRoomId());
        room.setBedNum(bedNum);
        if (bedNum <= 4) {
            room.setRoomType(bedNum);
        } else {
            room.setRoomType(4);
        }
        //修改房间床位数量
        int m = roomService.updateById(room);

        //写入护理等级名称
        /*OmcLevelCare omcLevelCare = levelCareService.selectByKey(bed.getLevelCareId());
        if (PublicUtil.isEmpty(omcLevelCare)){
            return WrapMapper.wrap(Wrapper.ERROR_CODE, cmnyMessageSource.getMessage("levelCare.the.null", null), null);
        }
        bed.setLevelCareName(omcLevelCare.getNursingCare());*/

        //插入床位
        int n = bedService.insert(bed);
        if (n <= 0) {
//            return WrapMapper.wrap(Wrapper.ERROR_CODE, "添加失败", null);
            return WrapMapper.wrap(Wrapper.ERROR_CODE, cmnyMessageSource.getMessage("comment.add.fail", null), null);
        }
//        return WrapMapper.wrap(Wrapper.SUCCESS_CODE, "添加成功", null);
        return WrapMapper.wrap(Wrapper.SUCCESS_CODE, cmnyMessageSource.getMessage("comment.add.success", null), null);
    }

    //根据id删除床位
    @RequestMapping(value = "/delBedById", method = RequestMethod.POST)
    public Wrapper delBedById(Integer bedId) {
        if (bedId == null) {
//            return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, "床位id不能为空", null);
            return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, cmnyMessageSource.getMessage("Bed.bed.id.null", null), null);
        }
        Bed bed = new Bed();
        bed.setBedId(bedId);
        //判断床位是否有老人入住
        Bed bed1 = bedService.selectByBed(bed);

        /**
         * @author: huangxm
         * @date 2019-03-06
         * 添加被删除的床位是否存在的逻辑 防止下一行bed1.getOldmanId() 报空指针异常
         */
        //判断该床位是否存在
        if (bed1 == null) {
//            return WrapMapper.wrap(Wrapper.ERROR_CODE, "该床位不存在,无法删除", null);
            return WrapMapper.wrap(Wrapper.ERROR_CODE, cmnyMessageSource.getMessage("bed.not.exsit", null), null);
        }

        if (bed1.getOldmanId() != null) {
//            return WrapMapper.wrap(Wrapper.ERROR_CODE, "该床位有老人,不能删除", null);
            return WrapMapper.wrap(Wrapper.ERROR_CODE, cmnyMessageSource.getMessage("bed.is.use", null), null);
        }
        //预留床位是否绑定床垫和紧急按钮判断
        /*
        //床垫
        if (bed1.getMattressId() != null) {
        }
        //紧急按钮
        if (bed1.getAlarmButtonId() != null) {
        }*/
        //删除床位
        int m = bedService.deleteById(bedId);
        if (m <= 0) {
//            return WrapMapper.wrap(Wrapper.ERROR_CODE, "没有此id", null);
            return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, cmnyMessageSource.getMessage("bed.not.exsit", null), null);
        }
        //将房间的床位数量进行减一
        Room room = roomService.selectById(bed1.getRoomId());
        room.setBedNum(room.getBedNum() - 1);

        /**
         * @author: huangxm
         * @date 2019-03-06
         * 修改删除床位后房间类型随之改变的逻辑
         */
        Integer bedNum = room.getBedNum();
        if (bedNum >= 0) {
            if (bedNum == 0) {
                room.setRoomType(1);
            } else if (bedNum >= 1 && bedNum <= 3) {
                room.setRoomType(bedNum);
            } else {
                room.setRoomType(4);
            }
        }
        int n = roomService.updateById(room);
        if (n <= 0) {
            logger.info("删除床位时修改房间的床位数量失败");
        }
        return WrapMapper.wrap(Wrapper.SUCCESS_CODE, cmnyMessageSource.getMessage("operation.success", null), m);
    }

    //修改床位
    @RequestMapping(value = "/updateBed", method = RequestMethod.POST)
    public Wrapper updateBed(Bed bed) {

//        bed.setBedAlias(null);
        //校验
        if (bed.getBedId() == null) {
//            return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, "床位id不能为空", null);
            return WrapMapper.wrap(Wrapper.ERROR_CODE, cmnyMessageSource.getMessage("bed.id.null", null), null);
        }
        //判断是否修改了床位编号
        if (bed.getBedNo() != null) {
            Bed bed1 = new Bed();
            bed1.setBedId(bed.getBedId());
            Bed bed2 = bedService.selectByBed(bed1);
            //查询该楼栋的床位编号方式(1 按房间计数 2 按楼层计数)及房间信息
            Map<String, Object> buildingAndRoom = roomService.selectBuildingAndRoom(bed2.getRoomId());
            //获取编号方式
            Integer bedNoType = (Integer) buildingAndRoom.get("bedNoType");
            Bed bed3 = new Bed();
            bed3.setBedNo(bed.getBedNo());
            bed3.setRoomId(bed2.getRoomId());
            //按照房间计数
            if (bedNoType != null && bedNoType == 1) {
                //根据房间id和房间编号查询床位编号在该房间中是否重复
                Bed bed4 = bedService.selectByBed(bed3);
                if (bed4 != null && bed4.getBedId().intValue() != bed.getBedId().intValue()) {
//                    return WrapMapper.wrap(Wrapper.ERROR_CODE, "该床位已经在房间中存在", null);
                    return WrapMapper.wrap(Wrapper.ERROR_CODE, cmnyMessageSource.getMessage("Bed.have.repeat.num", null), null);
                }
            }
            //按照楼层计数
            if (bedNoType != null && bedNoType == 2) {
                //根据房间id和房间编号查询床位编号在楼层中是否重复
                Bed bed5 = bedService.selectByRidAndBedNo(bed3);
                if (bed5 != null && bed5.getBedId().intValue() != bed.getBedId().intValue()) {
                    return WrapMapper.wrap(Wrapper.ERROR_CODE, cmnyMessageSource.getMessage("Bed.floor.repeat.num", null), null);
                }
            }
        }

        int n = bedService.updateById(bed);
        if (n <= 0) {
//            return WrapMapper.wrap(Wrapper.ERROR_CODE, "修改失败", null);
            return WrapMapper.wrap(Wrapper.ERROR_CODE, cmnyMessageSource.getMessage("comment.change.fail", null), null);
        }

        // redis更新床位
        redisInitRunner.refreshBed(bed.getBedId());
//        return WrapMapper.wrap(Wrapper.SUCCESS_CODE, "修改成功", n);
        return WrapMapper.wrap(Wrapper.SUCCESS_CODE, cmnyMessageSource.getMessage("comment.change.success", null), null);
    }

    //根据BedId查询床位信息
    @RequestMapping(value = "/selectByBedId", method = RequestMethod.POST)
    public Wrapper selectByBedId(Integer bedId) {
        if (bedId == null) {
            return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, cmnyMessageSource.getMessage("Bed.bed.id.null", null), null);
        }
        BedVo bed = bedService.selectById(bedId);
        if (bed == null) {
//            return WrapMapper.wrap(Wrapper.ERROR_CODE, "没有此id", null);
            return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, cmnyMessageSource.getMessage("bed.not.exsit", null), null);
        }
//        return WrapMapper.wrap(Wrapper.SUCCESS_CODE, "查询成功", bed);
        return WrapMapper.wrap(Wrapper.SUCCESS_CODE, cmnyMessageSource.getMessage("operation.success", null), bed);
    }

    /**
     * 中控台 - 按照楼栋和楼层查询床位、老人、设备数据信息
     *
     * @param bedOldmanQueryDto bed oldman query dto
     * @param br                binding result
     * @return the wrapper.
     */
    @ValidateAnnotation
    @RequestMapping(value = "/queryBedOldmanDeviceWithList", method = RequestMethod.POST)
    public Wrapper queryBedOldmanDeviceWithList(@Validated @RequestBody BedOldmanQueryDto bedOldmanQueryDto,
                                                BindingResult br) {

        bedOldmanQueryDto.setGroupId(getLoginAuthDto().getGroupId());
        BedOldmanDeviceDataVo bedOldmanDeviceDataVo = bedService.queryBedOldmanDeviceWithList(bedOldmanQueryDto);

//         return WrapMapper.ok(bedOldmanDeviceDataVo);
        return WrapMapper.wrap(Wrapper.SUCCESS_CODE, cmnyMessageSource.getMessage("operation.success", null), bedOldmanDeviceDataVo);
    }

    /**
     * 中控台 - 按照楼栋和楼层查询床位、老人、设备数据、设备报警信息
     *
     * @param bedOldmanQueryDto bed oldman query dto
     * @param br                binding result
     * @return the wrapper.
     */
    @ValidateAnnotation
    @RequestMapping(value = "/queryBedOldmanDeviceAndAlertWithList", method = RequestMethod.POST)
    public Wrapper queryBedOldmanDeviceAndAlertWithList(@Validated @RequestBody BedOldmanQueryDto bedOldmanQueryDto,
                                                        BindingResult br) {

        bedOldmanQueryDto.setGroupId(getLoginAuthDto().getGroupId());
        BedOldmanDeviceAlertDataVo bedOldmanDeviceAlertDataVo = bedService.queryBedOldmanDeviceAndAlertWithList(bedOldmanQueryDto);
//        return WrapMapper.ok(bedOldmanDeviceAlertDataVo);
        return WrapMapper.wrap(Wrapper.SUCCESS_CODE, cmnyMessageSource.getMessage("operation.success", null), bedOldmanDeviceAlertDataVo);
    }

    /**
     * 中控台 - 按照机构、楼栋、楼层查询床位、老人、设备数据、设备报警信息
     *
     * @param bedOldmanQueryDto bed oldman query dto
     * @return the wrapper.
     */
    @RequestMapping(value = "/queryBedOldmanDeviceAndAlertByGroupId", method = RequestMethod.POST)
    public Wrapper queryBedOldmanDeviceAndAlertByGroupId(@RequestBody BedOldmanQueryDto bedOldmanQueryDto) {
        BedOldmanDeviceAlertDataVo bedOldmanDeviceAlertDataVo = bedService.queryBedOldmanDeviceAndAlertByGroupId(bedOldmanQueryDto);
//        return WrapMapper.ok(bedOldmanDeviceAlertDataVo);
        return WrapMapper.wrap(Wrapper.SUCCESS_CODE, cmnyMessageSource.getMessage("operation.success", null), bedOldmanDeviceAlertDataVo);
    }

    /**
     * 床位编号重排
     *
     * @param bedDto
     * @return
     */
    @ValidateAnnotation
    @RequestMapping(value = "/bedNoReset", method = RequestMethod.POST)
    public Wrapper bedNoReset(@RequestBody BedDto bedDto) {

        //校验
        List<Bed> bedList = bedDto.getBedList();
        if (CollectionUtils.isEmpty(bedList)) {
            return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, cmnyMessageSource.getMessage("Bed.bed.change.null", null), null);
        }

        //获取床位号排布类型
        Room room = roomService.selectById(bedList.get(0).getRoomId());
        Building building = buildingService.selectById(room.getBuildingId());
        Integer bedNoType = building.getBedNoType();
        if(bedNoType == null){
            return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, cmnyMessageSource.getMessage("Building.bedNoType.null", null), null);
        }

        //判断床位编号方式 1 按房间计数(房间内编号不能重复) 2 按楼层计数（楼层内编号不能重复）
        if(bedNoType == 1){
            //获取房间id集合
            Set<Integer> roomIdSet = bedList.stream().map(b -> b.getRoomId()).collect(Collectors.toSet());
            for(Integer roomId : roomIdSet){
                //判断每个房间内床位编号是否重复
                List<Integer> bedNoList = new LinkedList<>();
                for(Bed bed : bedList){
                    if(bed.getRoomId().equals(roomId)){
                        bedNoList.add(bed.getBedNo());
                    }
                }
                Set bedNoSet = new HashSet<>(bedNoList);
                if(bedNoList.size() != bedNoSet.size()){
                    return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, cmnyMessageSource.getMessage("Bed.have.repeat.num", null), null);
                }
                bedNoList.clear();
                bedNoSet.clear();
            }
            int n = bedService.bedUpdateList(bedList);
            return WrapMapper.wrap(Wrapper.SUCCESS_CODE, cmnyMessageSource.getMessage("Bed.bed.change.success", null), n);
        }else if(bedNoType == 2){
            //校验该楼层床位号是否重复
            List<Integer> bedNoList = bedList.stream().map(b->b.getBedNo()).collect(Collectors.toList());
            Set bedNoSet = new HashSet<>(bedNoList);
            if(bedNoList.size() != bedNoSet.size()){
                return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, cmnyMessageSource.getMessage("Bed.floor.repeat.num", null), null);
            }
            int n = bedService.bedUpdateList(bedList);
            return WrapMapper.wrap(Wrapper.SUCCESS_CODE, cmnyMessageSource.getMessage("Bed.bed.change.success", null), n);
        }else{
            return WrapMapper.wrap(Wrapper.SUCCESS_CODE, cmnyMessageSource.getMessage("Building.bedNoType.null", null), null);
        }
    }

    /**
     * 根据楼栋、楼层查询房间内床位信息
     * @param: [buildingId, floorNo]
     * @return: com.csun.cmny.util.wrapper.Wrapper
     */
    @ValidateAnnotation
    @RequestMapping(value = "/queryBedInfo", method = RequestMethod.POST)
    public Wrapper queryBedInfo(@RequestBody BedInfoQueryDto bedInfoQueryDto) {
        if(bedInfoQueryDto == null){
            return WrapMapper.wrap(Wrapper.ERROR_CODE, cmnyMessageSource.getMessage("operation.failed", null));
        }
        List<BedInfoVo> voList = bedService.queryBedInfo(bedInfoQueryDto.getBuildingId(),bedInfoQueryDto.getFloorNo(),bedInfoQueryDto.getRoomId(),bedInfoQueryDto.getGroupId(),getLoginAuthDto());
//        return WrapMapper.ok(voList);
        return WrapMapper.wrap(Wrapper.SUCCESS_CODE, cmnyMessageSource.getMessage("operation.success", null), voList);
    }

    /**
     * 统计院内床位状况
     * @param: []
     * @return: com.csun.cmny.util.wrapper.Wrapper
     */
    @ValidateAnnotation
    @RequestMapping(value = "/queryBedStatus/{buildingId}", method = RequestMethod.POST)
    public Wrapper queryBedStatus(@PathVariable Integer buildingId) {

        // 校验advisoryId是否为空
        Preconditions.checkArgument(buildingId != null, cmnyMessageSource
                .getMessage("building.id.null", null));
        List<BedStatusVo> voList = bedService.queryBedStatus(buildingId,getLoginAuthDto());
//        return WrapMapper.ok(voList);
        return WrapMapper.wrap(Wrapper.SUCCESS_CODE, cmnyMessageSource.getMessage("operation.success", null), voList);
    }

    /*
    * 集团化床位查询
    * */
    @PostMapping("/selectBedInfor")
    public Wrapper selectBedInfor(@RequestBody BedInfoQueryDto bedInfoQueryDto) {
        if(bedInfoQueryDto != null){
            WrapMapper.wrap(Wrapper.ERROR_CODE, cmnyMessageSource.getMessage("operation.failed", null));
        }
        List<BedInfoVo> voList = bedService.selectBedInfor(bedInfoQueryDto.getBuildingId(), bedInfoQueryDto.getFloorNo(), bedInfoQueryDto.getRoomId(), bedInfoQueryDto.getGroupId());
        return WrapMapper.wrap(Wrapper.SUCCESS_CODE, cmnyMessageSource.getMessage("operation.success", null), voList);
    }
}
